package com.lxd;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class LindTokenAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserDetailsService userDetailsService;

    String tokenHead = "SANGE ";
    //自定义头
    String tokenHeader = "Authorization";

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        //拿到请求头
        String authHeader = request.getHeader(this.tokenHeader);
        //"Authorization":"SANGE zhangsan"
        //SANGE zhangsan
        //判断发过来的请求非空 并且要以前面自定义的 "tokenHead"开头
        if (authHeader != null && authHeader.startsWith(tokenHead)) {
            //截取tokenHead后的内容 作为tokenId
            final String authToken = authHeader.substring(tokenHead.length()); // The part after "Bearer "
            //token不为空 并且数据库中能查到改token则进行下面的操作
            if (authToken != null && redisTemplate.hasKey(authToken)) {
                //根据token找到数据库中的用户名
                String username = redisTemplate.opsForValue().get(authToken);
                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    UserDetails userDetails =
                            this.userDetailsService.loadUserByUsername(username);
                    //可以校验token和username是否有效，目前由于token对应username存在redis，都以默认都是有效的
                    UsernamePasswordAuthenticationToken authentication =
                            new UsernamePasswordAuthenticationToken(
                                    userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
                            request));
                    logger.info("authenticated user " + username + ", setting security context");
                    System.out.println(userDetails);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}
